package com.gzz.common.base;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.scheduling.annotation.Async;

import com.gzz.common.tools.DateUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * @功能描述 【数据访问】基类
 * @author 高振中
 * @date 2021-02-01 20:20:20
 */
@Slf4j
public class BaseTemplate {

	@Autowired
	protected JdbcTemplate jdbcTemplate;
	@Autowired
	protected NamedParameterJdbcTemplate nameJdbcTemplate;

	/**
	 * @功能描述 分页查询
	 */
	final protected <T, C extends BaseCondition> Page<T> page(final String sql, C cond, final Class<T> clazz) {
		String countSQL = sql.replaceAll("(?i)(SELECT)(.*)(?i)(FROM)", "$1 count(1) $3");// 高效不支持嵌套
// 		log.info(sql(countSQL, cond.array()));
		int rowCount = jdbcTemplate.queryForObject(countSQL, cond.array(), Integer.class);
		int pageSize = cond.getSize();
		int curPage = cond.getPage() - 1;
		StringBuffer listSQL = new StringBuffer(sql + " LIMIT " + curPage * pageSize + "," + pageSize);
// 		log.info(sql(listSQL.toString(), cond.array()));	 
		List<T> dataList = jdbcTemplate.query(listSQL.toString(), cond.array(), new BeanPropertyRowMapper<T>(clazz));
		return new Page<T>(dataList, pageSize, rowCount, curPage);
	}
 
	/**
	 * @功能描述 批操作
	 */
	final protected <T> int[] batchOperate(final List<T> list, final String sql) {
		return nameJdbcTemplate.batchUpdate(sql, list.stream().map(i -> new BeanPropertySqlParameterSource(i)).collect(Collectors.toList()).toArray(new BeanPropertySqlParameterSource[] {}));
	}

	/**
	 * @功能描述 保存数据返回主键
	 */
	final protected <T> int saveKey(final T t, String sql, final String id) {
		KeyHolder keyHolder = new GeneratedKeyHolder();
		nameJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(t), keyHolder, new String[] { id });
		return keyHolder.getKey().intValue();
	}
	/**
	 * @方法说明:解析带参数的SQL语句
	 */
	@Async
	final protected static String sql(String sql, final Object... object) {
		for (Object obj : object) {
			sql = sql.replaceFirst("[?]", parse(obj));
		}
		return sql;
	}

	private static String parse(Object obj) {
		if (null == obj)
			return "NULL";
		if (obj instanceof LocalDateTime)
			return "'" + DateUtils.formmatAll((LocalDateTime) obj) + "'";
		if (obj instanceof LocalDate)
			return "'" + DateUtils.formmatYmd((LocalDate) obj) + "'";
		if (obj instanceof LocalTime)
			return "'" + DateUtils.formmatHms((LocalTime) obj) + "'";
		if (obj instanceof String)
			return "'" + obj.toString() + "'";
		return obj.toString();
	}

	/**
	 * @方法说明 解析带参数的SQL语句
	 */
	@Async
	final protected static <T> String sqlp(String sql, List<T> list) {
		StringBuffer sb = new StringBuffer("\r\n");
		for (T t : list) {
			String row = new String(sql);
			for (Field field : t.getClass().getDeclaredFields()) {
				try {
					field.setAccessible(true);
					Object value = field.get(t);
					row = row.replaceFirst(":" + field.getName(), parse(value));
				} catch (IllegalArgumentException | IllegalAccessException e) {
					log.error("生成SQL时发生异常!!", e);
				}
			}
			sb.append(row + ";\r\n");
		}
		return sb.toString();
	}

	/**
	 * @方法说明 把组数拼接成(?,?,?)的形式
	 */
	final protected static String toIn(Object... ids) {
		return BaseCondition.toIn(ids);
	}
}